package com.supor.aiot.home.utils;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.TrafficStats;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.text.format.Formatter;

import com.android.baseconfig.common.utils.Logc;
import com.supor.aiot.home.bean.PingResult;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * ---------------------------------------------------------------- <br>
 * Copyright (C) 2014-2020, by het, Shenzhen, All rights reserved.  <br>
 * ---------------------------------------------------------------- <br>
 * <p>
 * 描述: NetSpeedUtils <br>
 * 作者: lei <br>
 * 日期: 2021/7/7 <br>
 */
public class NetSpeedUtils {
    private static long lastTotalRxBytes = 0;
    private static long lastTotalTxBytes = 0;
    private static long lastTimeStamp = 0;

    public static int getRxNetSpeed(Context context) {
        long nowTotalRxBytes = getTotalRxBytes(context.getApplicationInfo().uid);
        long nowTimeStamp = System.currentTimeMillis();
        long speedRx =
                ((nowTotalRxBytes - lastTotalRxBytes) * 1000 / (nowTimeStamp - lastTimeStamp));
        //毫秒转换
        lastTimeStamp = nowTimeStamp;
        lastTotalRxBytes = nowTotalRxBytes;
        Logc.d("网络-x-速度下行:" + (speedRx + " kB/s"));
        return (int) speedRx;
    }

    private static String getNetSpeed(Context context) {
        long nowTotalRxBytes = getTotalRxBytes(context.getApplicationInfo().uid);
        long nowTotalTxBytes = getTotalTxBytes(context.getApplicationInfo().uid);
        long nowTimeStamp = System.currentTimeMillis();
        long speedRx =
                ((nowTotalRxBytes - lastTotalRxBytes) * 1000 / (nowTimeStamp - lastTimeStamp));
        //毫秒转换
        long speedTx =
                ((nowTotalTxBytes - lastTotalTxBytes) * 1000 / (nowTimeStamp - lastTimeStamp));
        //毫秒转换
        lastTimeStamp = nowTimeStamp;
        lastTotalRxBytes = nowTotalRxBytes;
        lastTotalTxBytes = nowTotalTxBytes;
        Logc.d("网络-x-速度下行:" + (speedRx + " kB/s") + " 上行:" + speedTx + " kB/s");
        return speedRx + " kB/s";
    }

    /**
     * 下行 700kB/s 直播临界
     * 实际用到的流量
     *
     * @param uid getApplicationInfo().uid 当前线程
     * @return
     */
    public static long getTotalRxBytes(int uid) {
        return TrafficStats.getUidRxBytes(uid) == TrafficStats.UNSUPPORTED ? 0 :
                (TrafficStats.getTotalRxBytes() / 1024);//转为KB
    }

    /**
     * 上行实际用到的流量
     *
     * @param uid getApplicationInfo().uid 当前线程
     * @return
     */
    public static long getTotalTxBytes(int uid) {
        return TrafficStats.getUidRxBytes(uid) == TrafficStats.UNSUPPORTED ? 0 :
                (TrafficStats.getTotalTxBytes() / 1024);//转为KB
    }


    public static synchronized void ping(String ipAddress, int pingTimes, int timeOut, PingCallback callback) {
        long time = System.currentTimeMillis();
        PingResult pingResult = new PingResult();
        BufferedReader in = null;
        // 将要执行的ping命令,此命令是windows格式的命令
        Runtime r = Runtime.getRuntime();
        Process p = null;
        String pingCommand = "ping " + "-c " + pingTimes  + " -w " + timeOut + " " + ipAddress;
        // String pingCommand = "ping "  + " -w " + timeOut + " " + ipAddress;
        try {  // 执行命令并获取输出
            System.out.println(pingCommand);
            p = r.exec(pingCommand);
            Logc.d("----ping---", " = " );
            if (p == null) {
                if (callback != null) {
                    callback.onPingResult(pingResult);
                }
                return;
            }
            // 逐行检查输出,计算类似出现=23ms TTL=62字样的次数
            in = new BufferedReader(new InputStreamReader(p.getInputStream()));
            int connectedCount = 0;
            String line = null;
            while ((line = in.readLine()) != null) {
                Logc.d("----ping---", "line = " + line);
                // if (getCheckResult(line) == 1) {
                //     return true;
                // }
                connectedCount += getCheckResult(line, pingResult);
                if (callback != null) {
                    callback.onPing(connectedCount);
                }
            }   // 如果出现类似=23ms TTL=62这样的字样,出现的次数=测试次数则返回真
            Logc.d("----ping---", "end");

            if (callback != null && (System.currentTimeMillis() - time < 6000)) {
                callback.onPingResult(pingResult);
            }
        } catch (Exception ex) {
            ex.printStackTrace();  // 出现异常则返回假
            if (callback != null && (System.currentTimeMillis() - time < 6000)) {
                callback.onPingResult(pingResult);
            }
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (p != null) {
                    p.destroy();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //若line含有=18ms TTL=16字样,说明已经ping通,返回1,否則返回0.
    private static int getCheckResult(String line, PingResult pingResult) {
        Pattern pattern = Pattern.compile("(ttl=\\d+)",  Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(line.toLowerCase());
        while (matcher.find()) {
            return 1;
        }
        if (line.length() > 1) {
            if (line.contains("packets transmitted")) {
                line = line.replace("packets transmitted", "");
                line = line.replace("received", "");
                line = line.replace("packet loss", "");
                line = line.replace("time", "");
                String[] packetsArray = line.split(",");
                if (packetsArray.length == 4) {
                    pingResult.transmitted = packetsArray[0].trim();
                    pingResult.received = packetsArray[1].trim();
                    pingResult.loss = packetsArray[2].trim();
                    pingResult.time = packetsArray[3].trim();
                }
                Logc.e("transmitted: " + pingResult.toString());
            } else if (line.contains("min/avg/max")) {
                line = line.replace("rtt", "");
                line = line.replace("ms", "");
                String[] rttArray = line.split("=");
                if (rttArray.length == 2) {
                    String[] rttArray2 = rttArray[1].split("/");
                    pingResult.minRtt = rttArray2[0].trim();
                    pingResult.avgRtt = rttArray2[1].trim();
                    pingResult.maxRtt = rttArray2[2].trim();
                }
                Logc.e("rtt: " + pingResult.toString());
            }
        }
        return 0;
    }

    public interface PingCallback {
        void onPing(int count);
        void onPingResult(PingResult pingResult);
    }

    public static int getWifiConnectedNum(Context context) {
        ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        WifiManager wm = (WifiManager)context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);

        WifiInfo connectionInfo = wm.getConnectionInfo();
        int ipAddress = connectionInfo.getIpAddress();
        String ipString = Formatter.formatIpAddress(ipAddress);


        Logc.d("getWifiConnectedNum", "activeNetwork: " + String.valueOf(activeNetwork));
        Logc.d("getWifiConnectedNum", "ipString: " + String.valueOf(ipString));

        String prefix = ipString.substring(0, ipString.lastIndexOf(".") + 1);
        Logc.d("getWifiConnectedNum", "prefix: " + prefix);

        int count = 0;
        for (int i = 0; i < 255; i++) {
            String testIp = prefix + String.valueOf(i);

            InetAddress address = null;
            boolean reachable = false;
            try {
                address = InetAddress.getByName(testIp);
                reachable = address.isReachable(20);
            } catch (IOException e) {
                e.printStackTrace();
            }
            // String hostName = address.getCanonicalHostName();

            if (reachable) {
                count++;
                Logc.i("getWifiConnectedNum", "Host: " + "(" + String.valueOf(testIp) + ") is reachable!");
            }
        }
        Logc.d("getWifiConnectedNum", "count: " + count);
        return count;
    }
}
